package com.bss.search;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.persistence.Query;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.andy.basics.GenericDao;
import com.andy.basics.Service;

@Controller
@Scope("request")
public class SearchController extends com.andy.basics.Controller<SearchObject> {

	private static final int DAYS = 30 - 1;

	private static final long MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;

	private static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy");

	private static final Logger LOGGER = Logger.getLogger(SearchController.class);

	@Autowired
	private GenericDao genericDao;

	@Autowired
	private MessageSource messageSource;

	private AdvancedSearchParam advancedSearchParam = new AdvancedSearchParam();

	private String query;

	private List<?> list;

	private DataModel dataModel = null;

	public String getQuery() {
		return this.query;
	}

	public void setQuery(String query) {
		this.query = query;
	}

	@Override
	public SearchObject create() {
		return null;
	}

	@Override
	public Service<SearchObject> getService() {
		return null;
	}

	@Override
	public String select() {
		return null;
	}

	public String getMessage(String key) {
		return this.messageSource.getMessage(key, null, Locale.ENGLISH);
	}

	@Override
	public DataModel getData() {
		if (this.dataModel != null) {
			return this.dataModel;
		}
		if ((this.query == null) || this.query.isEmpty()) {
			return this.dataModel = null;
		}
		List<?> list = this.getItems();
		if ((list == null) || (list.size() == 0)) {
			return this.dataModel = null;
		}
		return this.dataModel = new ListDataModel(list);
	}

	public List<?> getItems() {
		if (this.list != null) {
			return this.list;
		}
		if ((this.query == null) || this.query.isEmpty()) {
			return this.list = null;
		}

		SearchController.LOGGER.info("Initializing data for new query " + this.getMessage("query." + this.query + ".queryString"));
		Query q = this.genericDao.getEntityManager().createQuery(this.getMessage("query." + this.query + ".queryString"));

		Date oldDate = new Date(new Date().getTime() - (SearchController.DAYS * SearchController.MILLISECONDS_PER_DAY));

		Calendar c = Calendar.getInstance();
		c.setTime(oldDate);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);

		SearchController.LOGGER.info("Old date is " + c.getTime());
		if ("occupiedRoomsOlder".equals(this.query)) {
			q.setParameter(1, c.getTime());
		} else if ("occupiedBedsOlder".equals(this.query)) {
			q.setParameter(1, c.getTime());
		} else if ("advancedSearch".equals(this.query)) {
			Date date1 = this.parseDate(this.advancedSearchParam.getDate1());

			if (date1 == null) {
				this.getMessageHandler().addMessage(
						"AdvancedSearch.Date1",
						"Invalid Date \"" + this.advancedSearchParam.getDate1()
								+ "\" for Advanced search - Date 1 - should be dd/mm/yyyy format and a valid date ! ");
				return null;
			}
			Date date2 = this.parseDate(this.advancedSearchParam.getDate2());

			if (date2 == null) {
				this.getMessageHandler().addMessage(
						"AdvancedSearch.Date2",
						"Invalid Date \"" + this.advancedSearchParam.getDate2()
								+ "\" for Advanced search - Date 2 - should be dd/mm/yyyy format and a valid date ! ");
				return null;
			}

			c = Calendar.getInstance();
			c.setTime(date2);
			c.set(Calendar.HOUR_OF_DAY, 23);
			c.set(Calendar.MINUTE, 59);

			q.setParameter(1, date1);
			q.setParameter(2, c.getTime());
		}

		List<?> list = q.getResultList();

		SearchController.LOGGER.info("Initializing data for new query " + this.getMessage("query." + this.query + ".queryString")
				+ " completed");

		if ((list == null) || (list.size() == 0)) {
			return this.list = null;
		}
		return this.list = list;
	}

	protected Date parseDate(String date1) {
		Date date = null;
		try {
			date = SearchController.DATE_FORMAT.parse(date1);
		} catch (ParseException e) {
		}
		return date;
	}

	public void setAdvancedSearchParam(AdvancedSearchParam advancedSearchParam) {
		this.advancedSearchParam = advancedSearchParam;
	}

	public AdvancedSearchParam getAdvancedSearchParam() {
		return this.advancedSearchParam;
	}

	public static class AdvancedSearchParam {

		private String date1;
		private String date2;

		public void setDate1(String date1) {
			this.date1 = date1;
		}

		public String getDate1() {
			return this.date1;
		}

		public void setDate2(String date2) {
			this.date2 = date2;
		}

		public String getDate2() {
			return this.date2;
		}
	}
}
